package com.turing.draw.examine.overtime;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
import com.turing.draw.client.procedure.ProcedureInnerService;
import com.turing.draw.enums.FileStatusEnum;
import com.turing.draw.enums.OcrPageTaskStatusEnum;
import com.turing.draw.enums.TaskStatusEnum;
import com.turing.draw.model.domain.DrawTask;
import com.turing.draw.model.domain.FileTask;
import com.turing.draw.model.domain.OcrPageTask;
import com.turing.draw.service.DrawTaskService;
import com.turing.draw.service.FileTaskService;
import com.turing.draw.service.OcrPageTaskService;
import com.turing.orm.handler.DateTableNameParser;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

@Component
public class TaskOvertimeSchedule {

    @Autowired
    private FileTaskService fileTaskService;

    @Autowired
    private OcrPageTaskService ocrPageTaskService;

    @Autowired
    private DrawTaskService drawTaskService;

    @Autowired
    private ProcedureInnerService procedureInnerService;

    @Value("${preprocess.retry.threshold}")
    private Integer PREPROCESS_RETRY_THRESHOLD;

    @Value("${ocr.retry.threshold}")
    private Integer OCR_RETRY_THRESHOLD;

    @Value("${draw.retry.threshold}")
    private Integer FORECAST_RETRY_THRESHOLD;

    @XxlJob(value="PreProcessorOvertimeExamine")
    @Transactional(propagation = Propagation.REQUIRED)
    public void PreProcessorOvertimeExamine() {

        FileTask preProcessorTask = fileTaskService.getOvertimeTaskByStatus(FileStatusEnum.PRETASKPROCESSING.getCode());
        Optional.ofNullable(preProcessorTask).ifPresent(p->resetTaskStatusOrFailed(p, PREPROCESS_RETRY_THRESHOLD, FileStatusEnum.UPLOADED.getCode(),"10002:预处理超时"));

    }

    @XxlJob(value="ForecastOvertimeExamine")
    @Transactional(propagation = Propagation.REQUIRED)
    public void ForecastOvertimeExamine() {

        FileTask forecastTask = fileTaskService.getOvertimeForecastTaskByStatus(FileStatusEnum.FORECASTTASKPROCESSING.getCode());
        Optional.ofNullable(forecastTask).ifPresent(f->resetTaskStatusOrFailed(f, PREPROCESS_RETRY_THRESHOLD, FileStatusEnum.OCRTASKFINISHED.getCode(),"10006:预测超时"));

    }


    @XxlJob(value="OcrOvertimeExamine")
    @Transactional(propagation = Propagation.REQUIRED)
    public void OcrOvertimeExamine() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = LocalDateTime.now().format(formatter);
        // check pending tasks overtime > now
        OcrPageTask ocrPageTask = ocrPageTaskService.lambdaQuery()
                .select(OcrPageTask::getParentTaskSn, OcrPageTask::getTaskSn, OcrPageTask::getOcrPageTaskSn, OcrPageTask::getRetryCount )
                .eq(OcrPageTask::getOcrPageTaskStatus, OcrPageTaskStatusEnum.OCRTASKPROCESSING.getCode())
                .apply("UNIX_TIMESTAMP(warning_time) < UNIX_TIMESTAMP('" + format + "')")
                .eq(OcrPageTask::getIsDel, 0)
                .last("limit 1")
                .one();

        if( ocrPageTask != null ){

            if( ocrPageTask.getRetryCount() <  OCR_RETRY_THRESHOLD ){

                // reset task status & retry count ++
                ocrPageTaskService.lambdaUpdate().eq( OcrPageTask::getOcrPageTaskSn, ocrPageTask.getOcrPageTaskSn() )
                        .set( OcrPageTask::getOcrPageTaskStatus, OcrPageTaskStatusEnum.QUEUING.getCode() )
                        .update();

            }else{

                // retry time > max retry time, task failed, delete all tasks
                fileTaskService.tasksFailed(ocrPageTask.getParentTaskSn(),"10004:ocr超时");

                // remove all tasks,task failed
                ocrPageTaskService.deleteByOcrPageTaskSn(ocrPageTask.getOcrPageTaskSn());

            }

        }

    }

    private void resetTaskStatusOrFailed(FileTask forecastTask, Integer threshold, Integer status,String errorMessage) {

        if (forecastTask.getPreProcessorRetryCount() < threshold) {

            // reset task status & retry count ++
            fileTaskService.lambdaUpdate().eq(FileTask::getTaskSn, forecastTask.getTaskSn())
                    .set(FileTask::getFileStatus, status)
                    .update();

        } else {

            // retry time > max retry time, task failed
            fileTaskService.tasksFailed(forecastTask.getParentTaskSn(),errorMessage);

        }

    }


}
